package web_util

import (
	app_global "app/app_src/framework/app/global"
	"app/app_src/framework/i18n"
	"bytes"
	"fmt"
	"html/template"
	"net/http"
	"net/url"
	"strings"

	"sync"

	"github.com/gin-gonic/gin"

	web_constants "app/app_src/framework/constant/web"

	template_wrapper "app/app_src/framework/template/wrapper"

	template_funcs "app/app_src/framework/template/funcs"

	url_mapping_util "app/app_src/framework/app/util/url_mapping"

	utl_pattern_util "app/app_src/framework/util/web/url_pattern"
)

// 缓存
var _HtmlCache sync.Map

func _InitHtmlUtil(utilContext *UtilContext) {
	config := utilContext.HtmlTemplateConfig

	if config != nil {
		mappingUrls := url_mapping_util.GetMappingUrlMap()
		funcMap := template.FuncMap{
			"libStatic":   template_funcs.NewLibStaticFunc(mappingUrls),
			"appStatic":   template_funcs.NewAppStaticFunc(mappingUrls),
			"t":           template_funcs.NewHtmI18nFunc(),
			"currentLang": template_funcs.NewCurrentLangFunc(),
			"basePath":    template_funcs.NewBasePathFunc(),
			"libLang":     template_funcs.NewLibLangFunc(mappingUrls),
		}

		var parser = template_wrapper.NewTemplateParser(template_wrapper.TEMPLATE_TYPE_HTML, funcMap)
		parser.LeftDelim = config.LeftDelim
		parser.RightDelim = config.RightDelim

		var loader = template_wrapper.NewTemplateLoader(config.PathPrefix, config.PathSuffix, parser)
		loader.CacheEnabled = config.CacheEnabled
		loader.UseEmbedFS = config.UseEmbedFS

		utilContext._HtmlTemplateLoader = loader
	} else {
		panic("UtilContext.HtmlTemplateConfig nil")
	}
}

// 设置响应头
func PageHeaders(ctx *gin.Context, pageCode string, pageName string) {
	request := ctx.Request
	requestUrl := request.URL
	pageUrl := strings.TrimSuffix(requestUrl.Path, app_global.ContextPath())

	pageName = url.PathEscape(pageName)
	urlPattern := utl_pattern_util.ConvertFormat(strings.TrimSuffix(ctx.FullPath(), app_global.ContextPath()))

	ctx.Header(web_constants.RESPONSE_HEADER_PAGE_CODE, pageCode)
	ctx.Header(web_constants.RESPONSE_HEADER_PAGE_NAME, pageName)
	ctx.Header(web_constants.RESPONSE_HEADER_PAGE_URL, pageUrl)
	ctx.Header(web_constants.RESPONSE_HEADER_URL_PATTERN, urlPattern)
}

func OkHTML(ctx *gin.Context, name string, obj any) {
	HTML(ctx, http.StatusOK, name, obj)
}

func HTML(ctx *gin.Context, code int, name string, obj any) {
	// 设置响应头
	ctx.Status(code)
	ctx.Header(web_constants.HEADER_CONTENT_TYPE, web_constants.RESPONSE_HEADER_CONTENT_TYPE_HTML)

	// 渲染模板
	_RenderTemplate(ctx, name, obj)
}

func _RenderTemplate(ctx *gin.Context, name string, obj any) {
	if obj == nil && _UtilContext.HtmlCacheEnabled {
		var html string
		cacheKey := fmt.Sprint(i18n.GetLangCode(), ":", name)

		// 从缓存中获取
		value, ok := _HtmlCache.Load(cacheKey)
		if ok {
			html = value.(string)
		} else {
			var writer bytes.Buffer
			tmpl := _UtilContext._HtmlTemplateLoader.LoadTemplate(name)
			// 渲染模板
			err := tmpl.RenderTemplate(&writer, obj)

			if err != nil {
				panic(err)
			}

			html = writer.String()
		}

		// 缓存渲染后的 HTML 内容
		_HtmlCache.Store(cacheKey, html)
		// 返回 HTML 内容给客户端
		ctx.Writer.Write([]byte(html))
		ctx.Writer.Flush()
	} else {
		tmpl := _UtilContext._HtmlTemplateLoader.LoadTemplate(name)
		// 渲染模板并返回给客户端
		err := tmpl.RenderTemplate(ctx.Writer, obj)

		if err != nil {
			panic(err)
		}
	}
}
